"""User views."""

import ldap
import uuid

from django import forms
from django.conf import settings
from hcp.auth.decorators import permission_required
from hcp.forms.choice import ChoiceWithOtherField
from hcp.forms.custom import MyDynamicField, MyGroupedForm
from hcp.forms.grouped import FormSection
from hcp.forms.util import form_from_model
from hcp.jinja import render_to_response
from hcp.ldap_models import Person, Group, update_model_from_post, set_auto_manual_id
from hcp.tracking import HcpCallback
from hcp.util.json import JsonResponse

uidNumber_choices = (('AUTO', 'Create new UID.'), ('MANUAL', 'Manually enter UID:'))
gidNumber_choices = (('AUTO', 'Create new GID.'), ('MANUAL', 'Manually enter GID:'))

textarea = forms.widgets.Textarea(attrs={'cols':40, 'rows': 4})

def create_user_form(new_user):

    class UserForm(MyGroupedForm):

        def __init__(self, *args, **kwargs):
            kwargs['filter_fields'] = settings.USER_FIELDS_EXCLUDE
            super(UserForm, self).__init__(*args, **kwargs)


        class Required(FormSection):

            label = 'Required Attributes'

            uid = MyDynamicField(forms.CharField(), label='Username')
            cn = MyDynamicField(forms.CharField(), label='Name')
            sn = MyDynamicField(forms.CharField(), label='Surname')
            uidNumber = [forms.IntegerField(min_value=0, label='UID Number'),
                         ChoiceWithOtherField(choices=uidNumber_choices,
                            initial=('AUTO', ''),
                            other_field=forms.IntegerField(min_value=0),
                            label='UID Number')
                        ][int(new_user)]
            gidNumber = [forms.IntegerField(min_value=0, label='GID Number'),
                         ChoiceWithOtherField(choices=gidNumber_choices,
                            initial=('AUTO', ''),
                            other_field=forms.IntegerField(min_value=0),
                            label='GID Number'),
                        ][int(new_user)]
            homeDirectory = forms.CharField(label='Home Directory')

        class MailAttributes(FormSection):

            label = 'Mail Attributes'

            mail = MyDynamicField(forms.EmailField(),
                                  label='Email Address',
                                  required=False)
            hcpMailLocation = forms.CharField(required=False, label='Mail Location')

        class PosixAttributes(FormSection):

            label = 'POSIX Attributes'

            userPassword = MyDynamicField(forms.CharField(widget=forms.widgets.PasswordInput),
                                label='Password',
                                required=False)
            gecos = forms.CharField(required=False, label='GECOS')
            loginShell = forms.CharField(required=False, label='Login Shell')

        class PersonalAttributes(FormSection):

            label = 'Personal Attributes'

            displayName = forms.CharField(required=False, label='Display Name')
            gn = MyDynamicField(forms.CharField(),
                                label='Given Name',
                                required=False)
            title = MyDynamicField(forms.CharField(),
                                label='Title',
                                required=False)
            homePhone = MyDynamicField(forms.CharField(),
                                label='Home Phone',
                                required=False)
            mobile = MyDynamicField(forms.CharField(),
                                label='Mobile Phone',
                                required=False)
            fax = MyDynamicField(forms.CharField(),
                                label='Fax Number',
                                required=False)
            telephoneNumber = MyDynamicField(forms.CharField(),
                                label='Telephone Number',
                                required=False)
            pager = MyDynamicField(forms.CharField(),
                                label='Pager',
                                required=False)
            initials = MyDynamicField(forms.CharField(),
                                label='Initials',
                                required=False)
            jpegPhoto = MyDynamicField(forms.CharField(),
                                label='Jpeg Photo',
                                required=False)
            o = MyDynamicField(forms.CharField(),
                                label='Organization',
                                required=False)
            ou = MyDynamicField(forms.CharField(),
                                label='Organizational Unit',
                                required=False)
            postalAddress = MyDynamicField(forms.CharField(widget=textarea),
                                label='Postal Address',
                                required=False)
            postalCode = MyDynamicField(forms.CharField(),
                                label='Postal Code',
                                required=False)
            homePostalAddress = MyDynamicField(forms.CharField(widget=textarea),
                                label='Home Address',
                                required=False)
            st = MyDynamicField(forms.CharField(),
                                label='State',
                                required=False)
            street = MyDynamicField(forms.CharField(),
                                label='Street Address',
                                required=False)
            description = MyDynamicField(forms.CharField(widget=textarea),
                                label='Description',
                                required=False)

        class Permissions(FormSection):

            label = 'Permissions'

            hcpPermission = MyDynamicField(forms.CharField(),
                                              label='Permission',
                                              required=False)

    return UserForm

@permission_required('manage_users')
def user_list(request):
    people = Person.objects.all()

    data = [ {'uid':person.uid[0],
              'cn':person.cn[0],
              'dn':person.dn} for person in people ]

    return JsonResponse({
        'users': data,
    })

@permission_required('manage_users')
def index(request):
    return render_to_response('users/index.html', request=request)

@permission_required('manage_users')
def new(request):
    UserForm = create_user_form(new_user=True)
    if request.method == 'POST':
        form = UserForm(request.POST, request.FILES)

        if form.is_valid():
            user = Person()
            fields = form.fields.keys()
            fields.remove('gidNumber')
            fields.remove('uidNumber')
            update_model_from_post(user, form.cleaned_data, fields)

            set_auto_manual_id('uidNumber', form, user, Person, settings.POSIX_MIN_UID)

            gid_type = form.cleaned_data['gidNumber'][0]
            if gid_type == 'AUTO':
                try:
                    group = Group.objects.get(cn=user.uid[0])
                except ldap.NO_SUCH_OBJECT:
                    # Figure out which gidNumber to use.
                    # Prefer the user's uidNumber.
                    try:
                        group = Group.objects.get(gidNumber=user.uidNumber)
                    except ldap.NO_SUCH_OBJECT:
                        # Good, it's not in use, they can stay in sync.
                        group = Group(cn=[user.uid[0]], gidNumber=user.uidNumber)
                    else:
                        # This gid number is already in use, use a new one.
                        group = Group(cn=[user.uid[0]], gidNumber=Group.next_gidNumber())
                group.save(callback=HcpCallback(request.user.uid))
                user.gidNumber = group.gidNumber
            elif gid_type == 'MANUAL':
                user.gidNumber = str(form.cleaned_data['gidNumber'][1])
            else:
                raise AssertionError(gid_type)

            # XXX:
            # - Change MANUAL entry to be a multi-select list.
            user.save(callback=HcpCallback(request.user.uid[0]))
            # XXX: Handle errors.
            # XXX: Make this a dialog instead of a separate page.
            return render_to_response('users/user_created.html', {'person': user}, request=request)
    else:
        form = UserForm()

    return render_to_response('users/new.html',
        {'form': form,
         'HOME_DIRECTORY': settings.HOME_DIRECTORY,
        }, request=request)

@permission_required('manage_users')
def edit(request, dn):
    UserForm = create_user_form(new_user=False)
    user = Person.objects.get_dn(dn)
    # XXX not found

    if request.method == 'POST':
        form = UserForm(request.POST, request.FILES)
        if form.is_valid():
            update_model_from_post(user, form.cleaned_data, form.fields.keys())
            user.save(callback=HcpCallback(request.user.uid[0]))
            # XXX: Handle errors.

            return render_to_response('users/user_edited.html', {'person': user}, request=request)
    else:
        form = form_from_model(UserForm, user)

    return render_to_response('users/edit.html',
        {'person': user,
         'form': form,
        },
        request=request)

@permission_required('manage_users')
def remove(request, dn):
    # XXX: Log errors.
    user = Person.objects.get_dn(dn)
    user.delete(callback=HcpCallback(request.user.uid[0]))
    return JsonResponse({
        'result': 'success',
    })
